package com.google.code.swingonfire.component.calendar;

import java.awt.Component;
import java.util.Calendar;

import com.google.code.swingonfire.component.page.old.JPageTransition;
import com.google.code.swingonfire.component.page.old.JPageTransitionAnimationFactory;
import com.google.code.swingonfire.component.page.old.JPageViewport;
import com.google.code.swingonfire.utility.interpolation.Interpolations;

public class JCalendarViewport extends JPageViewport implements JCalendarModelListener
{

    private static final long serialVersionUID = -8157079936363652791L;

    private final JCalendarModel model;

    public JCalendarViewport(JCalendarModel model)
    {
        super();

        this.model = model;

        model.addCalendarModelListener(this);

        setComponent(createMonthTable(model.getDisplayed()));
    }

    public JCalendarModel getModel()
    {
        return model;
    }

    protected void switchTo(JCalendarType type, Calendar calendar)
    {
        if (getCurrentType() != type)
        {
            switch (type)
            {
                case YEAR:
                    setComponent(createYearTable(calendar));
                    break;

                case MONTH:
                    setComponent(createMonthTable(calendar));
                    break;

                case ERA:
                case WEEK:
                default:
                    throw new IllegalArgumentException("Unsupported type");
            }

            return;
        }

        switch (type)
        {
            case MONTH:
                int compare = JCalendarUtils.compare(getCurrentCalendar(), calendar, Calendar.MONTH);

                if (compare == 0)
                {
                    return;
                }

                if (compare < 0)
                {
                    setAnimationFactory(new JPageTransitionAnimationFactory(0.25,
                        new JPageTransition().moveInFromRight(Interpolations.soft(), 1.0),
                        new JPageTransition().moveOutToLeft(Interpolations.soft(), 1.0)));
                }
                else
                {
                    setAnimationFactory(new JPageTransitionAnimationFactory(0.25, new JPageTransition().moveInFromLeft(
                        Interpolations.soft(), 1.0), new JPageTransition().moveOutToRight(Interpolations.soft(), 1.0)));
                }

                JMonthTable component = createMonthTable(calendar);

                component.setSize(getSize());

                setComponent(component);

                break;

            case ERA:
            case WEEK:
            case YEAR:
            default:
                throw new IllegalArgumentException("Unsupported type");
        }
    }

    protected JCalendarType getCurrentType()
    {
        Component component = getComponent();

        if (component == null)
        {
            return null;
        }

        if (component instanceof JYearTable)
        {
            return JCalendarType.YEAR;
        }

        if (component instanceof JMonthTable)
        {
            return JCalendarType.MONTH;
        }

        throw new IllegalStateException("Unrecognized component: " + component.getClass());
    }

    protected Calendar getCurrentCalendar()
    {
        Component component = getComponent();

        if (component == null)
        {
            return null;
        }

        if (component instanceof JYearTable)
        {
            Calendar calendar = (Calendar) model.getDisplayed().clone();

            calendar.set(Calendar.YEAR, ((JYearTable) component).getYear());

            return calendar;
        }

        if (component instanceof JMonthTable)
        {
            Calendar calendar = (Calendar) model.getDisplayed().clone();

            calendar.set(Calendar.YEAR, ((JMonthTable) component).getYear());
            calendar.set(Calendar.MONTH, ((JMonthTable) component).getMonth());

            return calendar;
        }

        throw new IllegalStateException("Unrecognized component: " + component.getClass());
    }

    protected JYearTable createYearTable(Calendar calendar)
    {
        return new JYearTable(model, calendar.get(Calendar.YEAR));
    }

    protected JMonthTable createMonthTable(Calendar calendar)
    {
        return new JMonthTable(model, calendar.get(Calendar.MONTH), calendar.get(Calendar.YEAR), true);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void calendarModelTypeChanged()
    {
        switchTo(model.getType(), model.getDisplayed());
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void calendarModelSelectionChanged()
    {
        // intentionally left blank
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void calendarModelDisplayChanged()
    {
        switchTo(model.getType(), model.getDisplayed());
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void calendarModelPropertyChanged(String property)
    {
        // intentionally left blank
    }

}
